/*
 * @Author: 火红色祥云 809880192@qq.com
 * @Date: 2023-11-25 15:04:17
 * @LastEditors: 火红色祥云 809880192@qq.com
 * @LastEditTime: 2023-11-26 12:22:58
 * @FilePath: /imx6ull-app/102_pwm/pwm.c
 * @Description: 通过export控制pwm输出
 */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>

#define PWM_CHIP_NUMBER 2  // Assuming PWM3 is on pwmchip2
#define PWM_CHANNEL_NUMBER 0

#define PWM_PATH "/sys/class/pwm/pwmchip%d/export"
#define PWM_CHANNEL_PATH "/sys/class/pwm/pwmchip%d/pwm%d"

#define PWD_CONFIG_ENABLE "/sys/class/pwm/pwmchip%d/pwm%d/enable"
#define PWD_CONFIG_PERIOD "/sys/class/pwm/pwmchip%d/pwm%d/period"
#define PWD_CONFIG_DUTY_CYCLE "/sys/class/pwm/pwmchip%d/pwm%d/duty_cycle"

int running = 1;

void export_pwm_channel() {
    char path[50];
    snprintf(path, sizeof(path), PWM_PATH, PWM_CHIP_NUMBER);

    int fd_export = open(path, O_WRONLY);
    if (fd_export == -1) {
        perror("Error opening export file");
        exit(EXIT_FAILURE);
    }

    // Export PWM channel
    snprintf(path, sizeof(path), "%d", PWM_CHANNEL_NUMBER);
    if (write(fd_export, path, strlen(path) + 1) == -1) {
        perror("Error exporting PWM channel");
        exit(EXIT_FAILURE);
    }

    close(fd_export);
}

void configure_pwm_enable() {
    char path[50];
    snprintf(path, sizeof(path), PWD_CONFIG_ENABLE, PWM_CHIP_NUMBER, PWM_CHANNEL_NUMBER);

    int fd_config = open(path, O_WRONLY);
    if (fd_config == -1) {
        perror("Error opening pwm config file");
        exit(EXIT_FAILURE);
    }

    write(fd_config, "1", 2);  // 50% duty cycle

    close(fd_config);
}
void configure_pwm_period() {
    char path[50];
    snprintf(path, sizeof(path), PWD_CONFIG_PERIOD, PWM_CHIP_NUMBER, PWM_CHANNEL_NUMBER);

    int fd_config = open(path, O_WRONLY);
    if (fd_config == -1) {
        perror("Error opening pwm config file");
        exit(EXIT_FAILURE);
    }

    write(fd_config, "1000000", 8); // 1ms period

    close(fd_config);
}
void configure_pwm_duty_cycle() {
    char path[50];
    snprintf(path, sizeof(path), PWD_CONFIG_DUTY_CYCLE, PWM_CHIP_NUMBER, PWM_CHANNEL_NUMBER);

    int fd_config = open(path, O_WRONLY);
    if (fd_config == -1) {
        perror("Error opening pwm config file");
        exit(EXIT_FAILURE);
    }

    write(fd_config, "500000", 7);  // 50% duty cycle

    close(fd_config);
}

void unexport_pwm_channel() {
    char path[50];
    snprintf(path, sizeof(path), PWM_PATH, PWM_CHIP_NUMBER);

    int fd_unexport = open(path, O_WRONLY);
    if (fd_unexport == -1) {
        perror("Error opening unexport file");
        exit(EXIT_FAILURE);
    }

    // Unexport PWM channel
    snprintf(path, sizeof(path), "%d", PWM_CHANNEL_NUMBER);
    if (write(fd_unexport, path, strlen(path) + 1) == -1) {
        perror("Error unexporting PWM channel");
        exit(EXIT_FAILURE);
    }

    close(fd_unexport);
}

void handle_sigint(int __attribute__((unused)) sig) {
    running = 0;
}

int main() {
    // Handle Ctrl+C
    signal(SIGINT, handle_sigint);

    // Export PWM channel
    export_pwm_channel();

    // Configure PWM
    configure_pwm_enable();
    configure_pwm_period();
    configure_pwm_duty_cycle();

    // Keep the program running
    while (running) {
        // Your PWM control logic goes here
        // You may use usleep or sleep to introduce delays or perform other operations
    }

    // Unexport PWM channel when the program is terminated
    unexport_pwm_channel();

    return 0;
}
